package org.yo.router.compiler;

import com.google.auto.service.AutoService;

import org.yo.router.annotation.common.CompilerUtil;
import org.yo.router.annotation.common.YoConstant;
import org.yo.router.compiler.base.BaseProcessor;

import java.io.BufferedWriter;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.util.HashSet;
import java.util.Set;

import javax.annotation.processing.ProcessingEnvironment;
import javax.annotation.processing.Processor;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedOptions;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.TypeElement;
import javax.tools.JavaFileObject;


/**
 * @author hailong
 * @date 2021年10月28日 4:03 下午
 * <p>
 * You never know what you can do until you try !
 * ----------------------------------------------------------------
 */
@AutoService(Processor.class)
@SupportedOptions(YoConstant.APPLICATION_NAME)
public class YoApplicationProcessor extends BaseProcessor {

    private final static String TAG_ANNOTATION = "org.yo.router.annotation.YoApplication";

    private String appProxyName;
    private String appProxyPackage;
    private org.yo.router.compiler.YoApplicationGenerator generator;


    @Override
    public synchronized void init(ProcessingEnvironment processingEnv) {
        super.init(processingEnv);
        appProxyPackage = YoConstant.APPLICATION_PACKAGE;
        String tagName = processingEnv.getOptions().get(YoConstant.APPLICATION_NAME);
        if (tagName.trim().length() <= 0) {
            appProxyName = "YoRouterManager";
        } else {
            appProxyName = CompilerUtil.makeClassName(tagName);
        }

        log("YoRouterName=>" + appProxyName);

        generator = new YoApplicationGenerator(appProxyPackage, appProxyName);

    }

    /**
     * {@inheritDoc}
     *
     * @param annotations
     * @param roundEnv
     */
    @Override
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {

        try {
            Class<Annotation> tagAnnotationClass = (Class<Annotation>) Class.forName(TAG_ANNOTATION);
            Set<? extends Element> tagElementsSet = roundEnv.getElementsAnnotatedWith(tagAnnotationClass);
            if (tagElementsSet.size() != 1) {
                return false;
            }
            JavaFileObject yoApplicationManagerJavaFileObject;
            yoApplicationManagerJavaFileObject = processingEnv.getFiler().createSourceFile(getAppProxyQualifyName());
            BufferedWriter bufferedWriter = new BufferedWriter(yoApplicationManagerJavaFileObject.openWriter());

            for (Element element : tagElementsSet) {
                if (element.getKind() == ElementKind.CLASS) {
                    String appPackage = element.getEnclosingElement().toString();
                    String appName = element.getSimpleName().toString();
                    generator.generateYoApplication(bufferedWriter, appPackage, appName);
                }
            }

            bufferedWriter.flush();

            bufferedWriter.close();

        } catch (ClassNotFoundException | IOException e) {
            e.printStackTrace();
        }

        return false;
    }

    @Override
    public Set<String> getSupportedAnnotationTypes() {
        Set<String> tagAnnotationSet = new HashSet<>();
        tagAnnotationSet.add(TAG_ANNOTATION);
        return tagAnnotationSet;
    }

    @Override
    public SourceVersion getSupportedSourceVersion() {
        return SourceVersion.latestSupported();
    }


    /**
     * 获取代理类的全限定名
     *
     * @return
     */
    private String getAppProxyQualifyName() {
        return appProxyPackage + "." + appProxyName;
    }

}
